from fisheye_manager import FisheyeManager
import fisheye_consts

class Link():
    """
    Represents a link between 2 nodes.
    """

    def __init__(self, node1, node2, capacity):
        self._node1 = node1
        self._node2 = node2
        self.capacity = capacity

    def __eq__(self, other):
        return sorted([self._node1, self._node2]) == sorted([other._node1, other._node2])


class LinkManager():
    """
    A class which is responsible for managing link state for each step.
    A link is a connection between 2 neigbouring nodes. In every step this will change.
    It has a certain capacity (how many of fragments it may send in this step) - it can only send complete packets.

    For example :  A link has a capacity of 5 fragments, and 2 packets are queued to be sent - one is 4 fragments, and
    the other one is 2 fragment. The 4-fragments packet will be sent - leaving the link capacity to 1 in this step - and
    then the 2-fragments packets won't be sent ("Entire packet or nothing") - leaving it to be sent in the next step.

    In each step, The manager will only hold links that data is being sent on. If no data is sent on a specific link -
    this link won't be in the manager in this current step.
    """
    def __init__(self):
        """
        Constructor.
        """
        self._initial_link_capacity = fisheye_consts.FISHEYE_LINK_FRGAMENTS_CAPACITY_PER_STEP
        self._links = []




    def send_on_link(self, link_src_node, link_dst_node, packet_size):
        """
        Checks that the current link capacity allows sending of the given packet.
        Creates the link in the links list if it does not exist. (a link between node "2" and "3" is the same as the link
        between "3" and "2")


        Returns True if packet was sent successfuly (and link capacity is then updated)
        """

        # Check if the link exists.
        link = Link(link_src_node, link_dst_node, self._initial_link_capacity)
        if link not in self._links:
            self._links.append(link)
        else:
            #Set link to the link object that holds the correct (current) capacity.
            link = self._links[self._links.index(link)]

        # Check if we can send the packet on this link.
        if packet_size <= link.capacity:
            link.capacity -= packet_size
            return True
        else:
            print "Packet can't be sent - link can currently carry %d but packet is of size: %d" \
                  % (link.capacity, packet_size)
            return False
